package com.ponhu.ea2.goodsCenter.provider.support;

import com.alibaba.fastjson.JSON;
import com.ponhu.ea2.properties.GoodsProperties;
import io.netty.util.concurrent.FastThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.UUID;

import static com.ponhu.ea2.constants.CommonConstant.MAX_LOG_PRINT_SIZE;

/**
 * 服务端日志Aop
 */
@Slf4j
@Aspect
@Component
public class LogAop {

    @Autowired
    private FastThreadLocal<String> traceIdLocal;

    @Resource
    GoodsProperties goodsProperties;

    @Pointcut("execution(* com.ponhu.ea2.goodsCenter.provider.*.*.*.*(..))")
    private void annotationAspect() {

    }

    @Around("annotationAspect()")
    public Object doAroundService(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String traceId = getTraceId();
        traceIdLocal.set(traceId);

        String servletPath = String.format("service path %s.%s",
                proceedingJoinPoint.getTarget().getClass().getSimpleName(),
                proceedingJoinPoint.getSignature().getName());
        try {
            log.info("{}[{}] ===>> 入参={}", servletPath, traceId, JSON.toJSONString(proceedingJoinPoint.getArgs()));
            Object proceed = proceedingJoinPoint.proceed();
            // 现在服务端追查日志不方便,增加出参信息
            // 剔除列表页日志信息，provider服务日志，暂时用字数来控制，以后需要考虑使用其他更好的方案来代替
            String logInfo = JSON.toJSONString(proceed);
            if (BooleanUtils.isTrue(goodsProperties.getEnableProviderLogPrintStatus())) {
                if (StringUtils.isNotBlank(logInfo) && !logInfo.contains("pageCount") && logInfo.length() < (goodsProperties.getMaxLogPrintSize() == null ? MAX_LOG_PRINT_SIZE : goodsProperties.getMaxLogPrintSize().intValue())) {
                    log.info("{} ===>> [{}] ===>> 出参={}", servletPath, traceId, logInfo);
                } else {
                    log.info("{} ===>> [{}] ===>> 请求成功", servletPath, traceId);
                }
            } else {
                log.info("{} ===>> [{}] ===>> 日志输出已关闭，请求成功", servletPath, traceId);
            }
            return proceed;
        } catch (Throwable throwable) {
            log.error("{}[{}] ===>> 异常: {}", servletPath, traceId, throwable);
            throw throwable;
        }
    }

    private static String getTraceId() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

}